`ifndef ARU_INTF_SVH
`define ARU_INTF_SVH
`include "param.svh"
`include "dtype.svh"
`include "isa.svh"



interface aru_ub_rdgen_cfg_if (
    input clk,
    input rst_n
);
    logic     vld;
    logic     rdy;
    ub_addr_t ub_base_addr;
    idx_t     slice_m;
    idx_t     slice_n;
    logic     reduce_m;
    idx_t     instr_idx;
    modport in(input vld, input ub_base_addr, input slice_m, input slice_n, input reduce_m, output rdy);
    modport out(output vld, output ub_base_addr, output slice_m, output slice_n, output reduce_m, input rdy);
    modport crd_gen_in(input vld, input slice_m, input slice_n, input reduce_m, output rdy);
    modport crd_gen_out(output vld, output slice_m, output slice_n, output reduce_m, input rdy);
    modport addr_calc_in(input vld, input ub_base_addr, input instr_idx, input slice_m, input slice_n, output rdy);
    modport addr_calc_out(output vld, output ub_base_addr, output instr_idx, output slice_m, output slice_n, input rdy);
endinterface

interface aru_ub_wrgen_cfg_if (
    input clk,
    input rst_n
);
    logic           vld;
    logic           rdy;
    ub_addr_t       ub_base_addr;
    idx_t           slice_m;
    idx_t           slice_n;
    logic           reduce_m;
    logic     [1:0] atomic_mode;
    idx_t           instr_idx;
    modport in(
        input vld,
        input ub_base_addr,
        input slice_m,
        input slice_n,
        input reduce_m,
        input instr_idx,
        input atomic_mode,
        output rdy
    );
    modport out(
        output vld,
        output ub_base_addr,
        output slice_m,
        output slice_n,
        output reduce_m,
        output instr_idx,
        output atomic_mode,
        input rdy
    );
    modport crd_gen_in(input vld, input slice_m, input slice_n, input reduce_m, input instr_idx, output rdy);
    modport crd_gen_out(output vld, output slice_m, output slice_n, output reduce_m, output instr_idx, input rdy);
    modport addr_calc_in(
        input vld,
        input ub_base_addr,
        input slice_m,
        input slice_n,
        input instr_idx,
        input atomic_mode,
        output rdy
    );
    modport addr_calc_out(
        output vld,
        output ub_base_addr,
        output slice_m,
        output slice_n,
        output instr_idx,
        output atomic_mode,
        input rdy
    );
endinterface

interface aru_psb_rdgen_cfg_if (
    input clk,
    input rst_n
);
    logic      vld;
    logic      rdy;
    psb_addr_t psb_base_addr;
    idx_t      slice_m;
    idx_t      slice_n;
    logic      reduce_m;
    idx_t      instr_idx;
    modport in(input vld, input psb_base_addr, input slice_m, input slice_n, input reduce_m, output rdy);
    modport out(output vld, output psb_base_addr, output slice_m, output slice_n, output reduce_m, input rdy);
    modport crd_gen_in(input vld, input slice_m, input slice_n, input reduce_m, output rdy);
    modport crd_gen_out(output vld, output slice_m, output slice_n, output reduce_m, input rdy);
    modport addr_calc_in(input vld, input psb_base_addr, input instr_idx, input slice_m, input slice_n, output rdy);
    modport addr_calc_out(
        output vld,
        output psb_base_addr,
        output instr_idx,
        output slice_m,
        output slice_n,
        input rdy
    );
endinterface

interface aru_arb_rdgen_cfg_if (
    input clk,
    input rst_n
);
    logic      vld;
    logic      rdy;
    arb_addr_t arb_addr;
    idx_t      slice_m;
    idx_t      slice_n;
    logic      broadcast_m;
    logic      broadcast_n;
    idx_t      instr_idx;
    modport in(
        input vld,
        input arb_addr,
        input slice_m,
        input slice_n,
        input broadcast_m,
        input broadcast_n,
        input instr_idx,
        output rdy
    );
    modport out(
        output vld,
        output arb_addr,
        output slice_m,
        output slice_n,
        output broadcast_m,
        output broadcast_n,
        output instr_idx,
        input rdy
    );
    modport crd_gen_in(input vld, input slice_m, input slice_n, input broadcast_m, input broadcast_n, output rdy);
    modport crd_gen_out(output vld, output slice_m, output slice_n, output broadcast_m, output broadcast_n, input rdy);
    modport addr_calc_in(
        input vld,
        input arb_addr,
        input instr_idx,
        input slice_m,
        input slice_n,
        input broadcast_m,
        input broadcast_n,
        output rdy
    );
    modport addr_calc_out(
        output vld,
        output arb_addr,
        output instr_idx,
        output slice_m,
        output slice_n,
        output broadcast_m,
        output broadcast_n,
        input rdy
    );
    modport broadcast_in(input vld, input broadcast_m, input broadcast_n, output rdy);
    modport broadcast_out(output vld, output broadcast_m, output broadcast_n, input rdy);
endinterface

interface aru_arb_wrgen_cfg_if (
    input clk,
    input rst_n
);
    logic      vld;
    logic      rdy;
    arb_addr_t arb_base_addr;
    idx_t      slice_m;
    idx_t      slice_n;
    logic      reduce_m;
    logic      reduce_n;
    idx_t      instr_idx;
    modport in(
        input vld,
        input arb_base_addr,
        input slice_m,
        input slice_n,
        input reduce_m,
        input reduce_n,
        input instr_idx,
        output rdy
    );
    modport out(
        output vld,
        output arb_base_addr,
        output slice_m,
        output slice_n,
        output reduce_m,
        output reduce_n,
        output instr_idx,
        input rdy
    );
    modport crd_gen_in(input vld, input slice_m, input slice_n, input broadcast_m, input broadcast_n, output rdy);
    modport crd_gen_out(output vld, output slice_m, output slice_n, output broadcast_m, output broadcast_n, input rdy);
    modport addr_calc_in(
        input vld,
        input arb_base_addr,
        input instr_idx,
        input slice_m,
        input slice_n,
        input broadcast_m,
        input broadcast_n,
        output rdy
    );
    modport addr_calc_out(
        output vld,
        output arb_base_addr,
        output instr_idx,
        output slice_m,
        output slice_n,
        output broadcast_m,
        output broadcast_n,
        input rdy
    );
endinterface

interface aru_gm_wrgen_cfg_if (
    input clk,
    input rst_n
);
    logic     vld;
    logic     rdy;
    gm_addr_t gm_base_addr;
    idx_t     slice_m;
    idx_t     slice_n;
    idx_t     instr_idx;
    modport in(input vld, input gm_base_addr, input slice_m, input slice_n, input instr_idx, output rdy);
    modport out(output vld, output gm_base_addr, output slice_m, output slice_n, output instr_idx, input rdy);
    modport crd_gen_in(input vld, input slice_m, input slice_n, output rdy);
    modport crd_gen_out(output vld, output slice_m, output slice_n, input rdy);
    modport addr_calc_in(input vld, input gm_base_addr, input instr_idx, input slice_m, input slice_n, output rdy);
    modport addr_calc_out(output vld, output gm_base_addr, output instr_idx, output slice_m, output slice_n, input rdy);

endinterface


interface aru_add_sub_cfg_if (
    input clk,
    input rst_n
);
    logic        vld;
    logic        rdy;
    logic        add_sub;  // 0: add, 1: sub
    logic  [2:0] mode;
    bf16_t       scalar;
    /* 
    0: 从上路输入数据，bypass输出到右路
    1: 从下路输入数据，bypass输出到右路
    2：从左路输入数据，bypass输出到右路
    3: 从上路和下路输入数据，计算后输出到右路
    4: 从下路输入数据，从cfg获得scalar，计算后输出到右路
    */
    modport in(input vld, input add_sub, input mode, input scalar, output rdy);
    modport out(output vld, output add_sub, output mode, output scalar, input rdy);
endinterface

interface aru_mul_cfg_if (
    input clk,
    input rst_n
);
    logic        vld;
    logic        rdy;
    logic  [2:0] mode;
    bf16_t       scalar;
    modport in(input vld, input mode, input scalar, output rdy);
    modport out(output vld, output mode, output scalar, input rdy);
endinterface

interface aru_div_cfg_if (
    input clk,
    input rst_n
);
    logic        vld;
    logic        rdy;
    logic  [2:0] mode;
    bf16_t       scalar;
    modport in(input vld, input mode, input scalar, output rdy);
    modport out(output vld, output mode, output scalar, input rdy);
endinterface

interface aru_max_min_cfg_if (
    input clk,
    input rst_n
);
    logic        vld;
    logic        rdy;
    logic        max_min;  // 0: max, 1: min
    logic  [2:0] mode;
    bf16_t       scalar;
    modport in(input vld, input max_min, input mode, input scalar, output rdy);
    modport out(output vld, output max_min, output mode, output scalar, input rdy);
endinterface

interface aru_unary_cfg_if (
    input clk,
    input rst_n
);
    logic  vld;
    logic  rdy;
    logic  en;
    bf16_t clamp_max;
    bf16_t clamp_min;
    modport in(input vld, input en, input clamp_max, input clamp_min, output rdy);
    modport out(output vld, output en, output clamp_max, output clamp_min, input rdy);
    modport no_clamp_in(input vld, input en, output rdy);
    modport no_clamp_out(output vld, output en, input rdy);
endinterface

interface aru_reduce_cfg_if (
    input clk,
    input rst_n
);
    logic       vld;
    logic       rdy;
    logic       reduce_m;
    logic       reduce_n;
    logic [1:0] reduce_op;  // 0: max, 1: min, 2: sum, 3: avg
    idx_t       slice_m;
    idx_t       slice_n;
    idx_t       instr_idx;

    modport in(
        input vld,
        input reduce_m,
        input reduce_n,
        input reduce_op,
        input slice_m,
        input slice_n,
        input instr_idx,
        output rdy
    );
    modport out(
        output vld,
        output reduce_m,
        output reduce_n,
        output reduce_op,
        output slice_m,
        output slice_n,
        output instr_idx,
        input rdy
    );
endinterface

interface aru_reduce_ctrl_if (
    input clk,
    input rst_n
);
    logic       vld;
    logic       rdy;
    logic       reduce_m;
    logic       reduce_n;
    logic [1:0] reduce_op;  // 0: max, 1: min, 2: sum, 3: avg
    idx_t       slice_m;
    idx_t       slice_n;
    idx_t       instr_idx;

    modport in(
        input vld,
        input reduce_m,
        input reduce_n,
        input reduce_op,
        input slice_m,
        input slice_n,
        input instr_idx,
        output rdy
    );
    modport out(
        output vld,
        output reduce_m,
        output reduce_n,
        output reduce_op,
        output slice_m,
        output slice_n,
        output instr_idx,
        input rdy
    );
endinterface

// 2-to-1 top, 2-to-1 bottom, 1-to-4 up, 1-to-4 down, psb 1-to-2, 1-to-3共享同一个interface
interface aru_mux_cfg_if (
    input clk,
    input rst_n
);
    logic       vld;
    logic       rdy;
    logic [1:0] mode;
    modport in(input vld, input mode, output rdy);
    modport out(output vld, output mode, input rdy);
endinterface

typedef struct packed {
    idx_t vld_m;
    idx_t vld_n;
    logic eon;
    logic eom;
} aru_sdb_t;

typedef struct packed {bf16_t [`P_ARU*`N0-1:0] dat;} aru_dat_t;

interface aru_sdb_if (
    input clk,
    input rst_n
);
    logic     vld;
    logic     rdy;
    aru_sdb_t pld;
    modport in(input vld, input pld, output rdy);
    modport out(output vld, output pld, input rdy);
endinterface

typedef struct packed {
    idx_t m1_idx;
    idx_t n1_idx;
    idx_t p_idx;
} aru_idx_t;

interface aru_idx_if (
    input clk,
    input rst_n
);
    logic     vld;
    logic     rdy;
    aru_idx_t pld;
    modport in(input vld, input pld, output rdy);
    modport out(output vld, output pld, input rdy);
endinterface

interface aru_payload_if (
    input clk,
    input rst_n
);
    logic     vld;
    logic     rdy;
    aru_dat_t dat;
    aru_sdb_t sdb;
    modport in(input vld, input dat, input sdb, output rdy);
    modport out(output vld, output dat, output sdb, input rdy);
endinterface

// interface aru_psb_dat_fp32_if (
//     input clk,
//     input rst_n
// );
//     logic     vld;
//     psb_dat_t dat;
//     logic     rdy;
//     modport in(input vld, input dat, output rdy);
//     modport out(output vld, output dat, input rdy);
// endinterface

interface aru_psb_dat_bf16_if (
    input clk,
    input rst_n
);
    logic     vld;
    aru_dat_t dat;
    logic     rdy;
    modport in(input vld, input dat, output rdy);
    modport out(output vld, output dat, input rdy);
endinterface

interface aru_arb_dat_if (
    input clk,
    input rst_n
);
    logic     vld;
    aru_dat_t dat;
    modport in(input vld, input dat);
    modport out(output vld, output dat);
endinterface

interface arb_rd_req_if (
    input clk,
    input rst_n
);
    logic      vld;
    arb_addr_t addr;
    modport in(input vld, input addr);
    modport out(output vld, output addr);
endinterface

interface arb_wr_req_if (
    input clk,
    input rst_n
);
    logic                            vld;
    arb_addr_t                       addr;
    bf16_t     [`P_ARU-1:0][`N0-1:0] dat;
    logic      [`P_ARU-1:0][`N0-1:0] msk;
    modport in(input vld, input addr, input dat, input msk);
    modport out(output vld, output addr, output dat, output msk);
endinterface

interface arb_rd_dat_if (
    input clk,
    input rst_n
);
    logic     vld;
    aru_dat_t dat;
    logic     rdy;
    modport in(input vld, input dat, output rdy);
    modport out(output vld, output dat, input rdy);
endinterface


// interface is_instr_if (
//     input clk,
//     input rst_n
// );
//     logic vld;
//     logic rdy;
//     isa_t pld;
//     modport in(input vld, input pld, output rdy);
//     modport out(output vld, output pld, input rdy);
// endinterface


`endif
